package com.example.demo.demos.web;


import com.example.demo.demos.web.ehcache.DelegeteEhCache;
import org.apache.ibatis.builder.InitializingObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.cache.Cache;

/**
 * 简单实现缓存使用ehcache3，暂无具体配置缓存配置策略
 */
public class MybatisEhcache3EhCache implements org.apache.ibatis.cache.Cache, InitializingObject {
    private Logger log = LoggerFactory.getLogger(MybatisEhcache3EhCache.class);
    private boolean logFlag = false;
    private boolean noExpiration = false;

    public boolean isNoExpiration() {
        return noExpiration;
    }

    public void setNoExpiration(boolean noExpiration) {
        this.noExpiration = noExpiration;
    }

    /**
     * Instantiates a new ehcache cache.
     *
     * @param id the id
     */
    public MybatisEhcache3EhCache(String id) {
        if (id == null) {
            throw new IllegalArgumentException("Cache instances require an ID");
        }
        this.id = id;
    }


    /**
     * The cache id (namespace).
     */
    protected final String id;

    /**
     * The cache instance.
     */
    protected org.apache.ibatis.cache.Cache cache;


    /**
     * {@inheritDoc}
     */
    @Override
    public void clear() {
        cache.clear();
        if (logFlag) {
            log.info("cache3 init id:" + id);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getId() {
        if (logFlag) {
            log.info("cache3 getId id:" + id);
        }
        return id;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Object getObject(Object key) {
        if (logFlag) {
            log.info("cache3 getObject key:" + key);
        }
        return cache.getObject(key);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int getSize() {
        if (logFlag) {
            log.info("cache3 getSize id:" + id);
        }
        return cache.getSize();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void putObject(Object key, Object value) {
        if (logFlag) {
            log.info("cache3 putObject key:" + key);
        }
        cache.putObject(key, value);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Object removeObject(Object key) {
        if (logFlag) {
            log.info("cache3 removeObject key:" + key);
        }
        Object obj = getObject(key);
        cache.removeObject(key);
        return obj;
    }

    /**
     * {@inheritDoc}
     */
    public void unlock(Object key) {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (!(obj instanceof Cache)) {
            return false;
        }

        Cache otherCache = (Cache) obj;
        return id.equals(otherCache.getName());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int hashCode() {
        return id.hashCode();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        return "EHCache {" + id + "}";
    }

    // DYNAMIC PROPERTIES
    private long _setTimeToIdleSeconds=0;

    /**
     * Sets the time to idle for an element before it expires. Is only used if the element is not eternal.
     *
     * @param timeToIdleSeconds the default amount of time to live for an element from its last accessed or modified date
     */
    public void setTimeToIdleSeconds(long timeToIdleSeconds) {
        _setTimeToIdleSeconds = timeToIdleSeconds;
    }

    private long _setTimeToLiveSeconds=0;

    /**
     * Sets the time to idle for an element before it expires. Is only used if the element is not eternal.
     *
     * @param timeToLiveSeconds the default amount of time to live for an element from its creation date
     */
    public void setTimeToLiveSeconds(long timeToLiveSeconds) {
        _setTimeToLiveSeconds = timeToLiveSeconds;
    }

    private long _setMaxEntriesLocalHeap=1000;

    /**
     * Sets the maximum objects to be held in memory (0 = no limit).
     *
     * @param maxEntriesLocalHeap The maximum number of elements in heap, before they are evicted (0 == no limit)
     */
    public void setMaxEntriesLocalHeap(long maxEntriesLocalHeap) {
        _setMaxEntriesLocalHeap = maxEntriesLocalHeap;
    }

    private long _setMaxEntriesLocalDisk;

    /**
     * Sets the maximum number elements on Disk. 0 means unlimited.
     *
     * @param maxEntriesLocalDisk the maximum number of Elements to allow on the disk. 0 means unlimited.
     */
    public void setMaxEntriesLocalDisk(long maxEntriesLocalDisk) {
        _setMaxEntriesLocalDisk = maxEntriesLocalDisk;
    }

    private String _setMemoryStoreEvictionPolicy;

    /**
     * Sets the eviction policy. An invalid argument will set it to null.
     * <p>
     * ehcache3 cache 暂时只有  LRU  FIFO，其中LRU为默认
     *
     * @param memoryStoreEvictionPolicy a String representation of the policy. One of "LRU", "LFU" or "FIFO".
     */
    public void setMemoryStoreEvictionPolicy(String memoryStoreEvictionPolicy) {
        _setMemoryStoreEvictionPolicy = memoryStoreEvictionPolicy;
    }

    public boolean isLogFlag() {
        return logFlag;
    }

    public void setLogFlag(boolean logFlag) {
        this.logFlag = logFlag;
    }

    @Override
    public void initialize() throws Exception {
        DelegeteEhCache xiner = new DelegeteEhCache();
        xiner.setId(id);
        xiner.setLogFlag(logFlag);
        xiner.setNoExpiration(noExpiration);
        xiner.setMaxEntriesLocalHeap(_setMaxEntriesLocalHeap);
        xiner.setTimeToIdleSeconds(_setTimeToIdleSeconds);
        xiner.setMaxEntriesLocalDisk(_setMaxEntriesLocalDisk);//忽略磁盘缓存，暂不支持
        xiner.setMemoryStoreEvictionPolicy(_setMemoryStoreEvictionPolicy);
        xiner.setTimeToLiveSeconds(_setTimeToLiveSeconds);
        xiner.initialize();
        cache=xiner;
    }
}
